﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Runtime.InteropServices;
using SocketControl.EventArgs;
using SocketControl.Log;

namespace SocketControl.Async
{
    public class SocketHandle : BaseSocketControl
    {
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        #region 事件定义

        /// <summary>
        /// 收到一个请求事件
        /// </summary>
        public override event OnAcceptEvent OnAccept;

        /// <summary>
        /// 接受数据完成事件
        /// </summary>
        public override event OnRecvCompletedEvent OnRecvCompleted;

        /// <summary>
        /// 发送数据完成事件
        /// </summary>
        public override event OnSendCompletedEvent OnSendCompleted;

        /// <summary>
        /// 错误事件
        /// </summary>
        public override event OnErrorEvent OnError;
        public Thread acceptThread = null;
        #endregion

        public SocketHandle()
            : base()
        {
        }

        public SocketHandle(Socket s)
        {
            localsocket = s;
        }

        public override void listen(int backlog = 100)
        {
            base.listen(backlog);
        }

        public override void bind(string ip, int port)
        {
            base.bind(ip, port);
        }


        /// <summary>
        /// 接收连接
        /// </summary>
        public override void accept()
        {
            if (acceptThread == null)
            {
                acceptThread = new Thread(new ThreadStart(acceptMethod));
                acceptThread.IsBackground = true;
                acceptThread.Start();
            }
        }

        void acceptMethod()
        {
            while (true & exit)
            {
                allDone.Reset();
                localsocket.BeginAccept(new AsyncCallback(acceptCallBack), this);
                allDone.WaitOne();
                //Thread.Sleep(1000);
            }
        }

        void acceptCallBack(IAsyncResult ar)
        {
            if (exit)
            {
                try
                {
                    remotesocket = new SocketHandle(((SocketHandle)ar.AsyncState).localsocket.EndAccept(ar));
                    if (remotesocket.localsocket.Connected)
                    {
                        if (remotesocket != null)
                        {
                            EventCompletedArgs e = new EventCompletedArgs();
                            e.workhandle = remotesocket;
                            e.buffer = new byte[recvcache];
                            if (this.OnAccept != null)
                            {
                                this.OnAccept(e);
                            }
                            if (exit)
                            {

                                remotesocket.localsocket.BeginReceive((byte[])e.buffer, 0, recvcache, 0,
                                    new AsyncCallback(AsyncRecv),
                                    e);
                            }
                        }
                    }
                }
                catch (Exception e)
                {

                    LogHelper.WriteError(this.GetType(), e);
                }
            }
        }

        void AsyncRecv(IAsyncResult ar)
        {
            if (exit)
            {
                allDone.Set();
                EventCompletedArgs handle = (EventCompletedArgs)ar.AsyncState;
                BaseSocketControl client = (SocketHandle)handle.workhandle;
                if (client.localsocket.Connected)
                {
                    byte[] recvTemp = handle.buffer != null ? (byte[])handle.buffer : new byte[0];
                    try
                    {
                        int result = client.localsocket.Connected ? client.localsocket.EndReceive(ar) : 0;
                        if (result > 0)
                        {
                            if (recvTemp.Length > 0)
                            {
                                if (tmp == null)
                                {
                                    tmp = new byte[0];
                                }
                                tmp = tmp.Concat(recvTemp).ToArray();
                                if (this.OnRecvCompleted != null)
                                {
                                    handle.buffer = tmp;
                                    tmp = new byte[0];
                                    OnRecvCompleted(handle);
                                }
                            }
                            if (exit & client.localsocket.Connected)
                            {
                                client.localsocket.BeginReceive((byte[])handle.buffer, 0, recvcache, 0,
                                    new AsyncCallback(AsyncRecv), handle);
                            }
                        }
                    }
                    catch (System.Exception e)
                    {
                        LogHelper.WriteError(this.GetType(), e);
                    }
                }
            }
        }

        public override void connect(string ip, int port)
        {
            base.connect(ip, port);
        }

        /// <summary>
        /// 发送包
        /// </summary>
        public override void send(byte[] buffer, bool depacket = true)
        {
            if (localsocket.Connected)
            {
                localsocket.Send(buffer);
            }
        }

        [Obsolete]
        public override void recv()
        {
            //base.recv();
        }

        public override void close()
        {
            exit = false;
            if (acceptThread != null)
            {
                acceptThread.Abort();
            }
            base.close();
        }
    }
}
